#pragma once

#include "poll.hh"
#include <atomic>
#include <optional>
#include <chrono>
#include <map>
#include <coroutine>

namespace wb
{
/**
 * @brief Poll Info encapsulates everything about a poll operation for the event
 * as well as its paired timeout.
 */
namespace detail
{
struct poll_info
{
    using clock = std::chrono::steady_clock;
    using time_point = clock::time_point;
    using timermap = std::multimap<time_point, poll_info*>;
    using optional_timermap_iter = std::optional<timermap::iterator>;
    struct poll_awaiter
    {
        explicit poll_awaiter(poll_info& p) : p_{p}
        {
        }
        bool await_ready() const noexcept
        {
            return false;
        }
        void await_suspend(std::coroutine_handle<> h)
        {
            p_.awaiting_coroutine = h;
            std::atomic_thread_fence(std::memory_order::release);
        }
        wb::poll_status await_resume() noexcept
        {
            return p_.status;
        }
        poll_info& p_;
    };

    poll_info() = default;
    ~poll_info() = default;
    poll_info& operator=(const poll_info&) = delete;
    poll_info& operator=(poll_info&&) = delete;
    poll_awaiter operator co_await() noexcept
    {
        return poll_awaiter{*this};
    }

    // The file descriptor being polled on
    int fd_{-1};
    // The iterator to the timeout in timermap
    optional_timermap_iter timer_iter{std::nullopt};
    // The coroutine for this poll info to resume upon event or timeout
    std::coroutine_handle<> awaiting_coroutine;
    // Status of poll
    wb::poll_status status{wb::poll_status::error};
    // Once set true, all future events on this poll_info will be null or void
    bool processed{false};
};

}  // namespace detail
}  // namespace wb